Skip to content

[lldb] Clear thread-creation breakpoints in ProcessGDBRemote::Clear #134397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

felipepiovezan
Copy link
Contributor

@felipepiovezan felipepiovezan commented Apr 4, 2025

Currently, these breakpoints are being accumulated every time a new process if created (e.g. through a run). Depending on the circumstances, the old breakpoints are even left enabled, interfering with subsequent processes. This is addressed by removing the breakpoints in ProcessGDBRemote::Clear

Note that these breakpoints are more of a PlatformDarwin thing, so in the future we should look into moving them there.

Currently, these breakpoints are being accumulated every time a new
process if created (e.g. through a `run`). Depending on the
circumstances, the old breakpoints are even left enabled, interfering
with subsequent processes. This is addressed by removing the breakpoints
in ProcessGDBRemote::Clear

Note that these breakpoints are more of a PlatformDarwin thing, so in
the future we should look into moving them there.
@llvmbot llvmbot added the lldb label Apr 4, 2025
@felipepiovezan felipepiovezan force-pushed the felipe/clear_thread_creation_bps branch from a1e12d0 to e7689b6 Compare April 4, 2025 15:05
@llvmbot
Copy link
Member

llvmbot commented Apr 4, 2025

@llvm/pr-subscribers-lldb

Author: Felipe de Azevedo Piovezan (felipepiovezan)

Changes

Currently, these breakpoints are being accumulated every time a new process if created (e.g. through a run). Depending on the circumstances, the old breakpoints are even left enabled, interfering with subsequent processes. This is addressed by removing the breakpoints in ProcessGDBRemote::Clear

Note that these breakpoints are more of a PlatformDarwin thing, so in the future we should look into moving them there.


Full diff: https://github.com/llvm/llvm-project/pull/134397.diff

2 Files Affected:

  • (modified) lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (+3)
  • (modified) lldb/test/API/macosx/thread_start_bps/TestBreakpointsThreadInit.py (+20)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 68360788c96e6..d7e8c2ce7944e 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -3410,6 +3410,9 @@ Status ProcessGDBRemote::DisableWatchpoint(WatchpointSP wp_sp, bool notify) {
 void ProcessGDBRemote::Clear() {
   m_thread_list_real.Clear();
   m_thread_list.Clear();
+  if (m_thread_create_bp_sp)
+    if (TargetSP target_sp = m_target_wp.lock())
+      target_sp->RemoveBreakpointByID(m_thread_create_bp_sp->GetID());
 }
 
 Status ProcessGDBRemote::DoSignal(int signo) {
diff --git a/lldb/test/API/macosx/thread_start_bps/TestBreakpointsThreadInit.py b/lldb/test/API/macosx/thread_start_bps/TestBreakpointsThreadInit.py
index 1c6fd4f91c73e..bf667f6f7d336 100644
--- a/lldb/test/API/macosx/thread_start_bps/TestBreakpointsThreadInit.py
+++ b/lldb/test/API/macosx/thread_start_bps/TestBreakpointsThreadInit.py
@@ -35,3 +35,23 @@ def test_internal_bps_resolved(self):
         for bp in bps:
             num_resolved += bp.GetNumResolvedLocations()
         self.assertGreater(num_resolved, 0)
+
+    @skipUnlessDarwin
+    def test_internal_bps_deleted_on_relaunch(self):
+        self.build()
+
+        source_file = lldb.SBFileSpec("main.c")
+        target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+            self, "initial hello", source_file
+        )
+
+        self.runCmd("break list --internal")
+        output = self.res.GetOutput()
+        self.assertEqual(output.count("thread-creation"), 1)
+
+        process.Kill()
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        self.runCmd("break list --internal")
+        output = self.res.GetOutput()
+        self.assertEqual(output.count("thread-creation"), 1)

Copy link
Collaborator

@jimingham jimingham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree these don't belong in ProcessGDBRemote, but this is a small and obvious change so it's fine to fix the status quo for now.

Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on what Jim said.

@felipepiovezan felipepiovezan merged commit 232525f into llvm:main Apr 4, 2025
10 checks passed
@felipepiovezan felipepiovezan deleted the felipe/clear_thread_creation_bps branch April 4, 2025 17:06
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Apr 4, 2025
…lvm#134397)

Currently, these breakpoints are being accumulated every time a new
process if created (e.g. through a `run`). Depending on the
circumstances, the old breakpoints are even left enabled, interfering
with subsequent processes. This is addressed by removing the breakpoints
in ProcessGDBRemote::Clear

Note that these breakpoints are more of a PlatformDarwin thing, so in
the future we should look into moving them there.

(cherry picked from commit 232525f)
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Apr 7, 2025
…lvm#134397)

Currently, these breakpoints are being accumulated every time a new
process if created (e.g. through a `run`). Depending on the
circumstances, the old breakpoints are even left enabled, interfering
with subsequent processes. This is addressed by removing the breakpoints
in ProcessGDBRemote::Clear

Note that these breakpoints are more of a PlatformDarwin thing, so in
the future we should look into moving them there.

(cherry picked from commit 232525f)
(cherry picked from commit 8afffeb)
jasonmolenda added a commit that referenced this pull request Apr 9, 2025
…:Clear (#134397)"

This reverts commit 232525f.

This change is causing test crashes while running
TestCompletion.py on Darwin systems, most of the CI runs
have failed since it has been merged in.
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Apr 11, 2025
…:Clear (llvm#134397)"

This reapplies commit 232525f.

The original commit triggered a sanitizer failure when Target was
destroyed. In Target::Destroy, `DeleteCurrentProcess` was called, but it
did not destroy the thread creation breakpoints for the underlying
ProcessGDBRemote, because said method would not call
`ProcessGDBRemote::Clear`.
Target then proceeded to destroy its breakpoints, which resulted in a
call to the destructor a std::vector containing the breakpoints. Through
a sequence of complicated events, destroying breakpoints caused the
reference count of the underlying to finally reach zero. This, in
turn, called `ProcessGDBRemote::Clear`, which attempted to destroy the
breakpoints. To do that, it would query back into the Target vector of
breakpoint, which we are in the middle of destroying.

We solve this by moving the breakpoint deletion into
`Process:DoDestroy`, which is a virtual Process method that will be
called much earlier.
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Apr 11, 2025
…:Clear (llvm#134397)"

This reapplies commit 232525f.

The original commit triggered a sanitizer failure when Target was
destroyed. In Target::Destroy, `DeleteCurrentProcess` was called, but it
did not destroy the thread creation breakpoints for the underlying
ProcessGDBRemote, because said method would not call
`ProcessGDBRemote::Clear`.
Target then proceeded to destroy its breakpoints, which resulted in a
call to the destructor a std::vector containing the breakpoints. Through
a sequence of complicated events, destroying breakpoints caused the
reference count of the underlying to finally reach zero. This, in
turn, called `ProcessGDBRemote::Clear`, which attempted to destroy the
breakpoints. To do that, it would query back into the Target vector of
breakpoint, which we are in the middle of destroying.

We solve this by moving the breakpoint deletion into
`Process:DoDestroy`, which is a virtual Process method that will be
called much earlier.
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Apr 11, 2025
…:Clear (llvm#134397)"

This reapplies commit 232525f.

The original commit triggered a sanitizer failure when `Target` was
destroyed. In `Target::Destroy`, `DeleteCurrentProcess` was called, but
it did not destroy the thread creation breakpoints for the underlying
`ProcessGDBRemote` because `ProcessGDBRemote::Clear` was not called in
that path.

`Target `then proceeded to destroy its breakpoints, which resulted in a
call to the destructor of a `std::vector` containing the breakpoints.
Through a sequence of complicated events, destroying breakpoints caused
the reference count of the underlying `ProcessGDBRemote` to finally
reach zero. This, in turn, called `ProcessGDBRemote::Clear`, which
attempted to destroy the breakpoints. To do that, it would go back into
the Target's vector of breakpoints, which we are in the middle of
destroying.

We solve this by moving the breakpoint deletion into
`Process:DoDestroy`, which is a virtual Process method that will be
called much earlier.
felipepiovezan added a commit that referenced this pull request Apr 11, 2025
…:Clear (#134397)" (#135296)

This reapplies commit
232525f.

The original commit triggered a sanitizer failure when `Target` was
destroyed. In `Target::Destroy`, `DeleteCurrentProcess` was called, but
it did not destroy the thread creation breakpoints for the underlying
`ProcessGDBRemote` because `ProcessGDBRemote::Clear` was not called in
that path.

`Target `then proceeded to destroy its breakpoints, which resulted in a
call to the destructor of a `std::vector` containing the breakpoints.
Through a sequence of complicated events, destroying breakpoints caused
the reference count of the underlying `ProcessGDBRemote` to finally
reach zero. This, in turn, called `ProcessGDBRemote::Clear`, which
attempted to destroy the breakpoints. To do that, it would go back into
the Target's vector of breakpoints, which we are in the middle of
destroying.

We solve this by moving the breakpoint deletion into
`Process:DoDestroy`, which is a virtual Process method that will be
called much earlier.
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Apr 11, 2025
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Apr 11, 2025
…:Clear (llvm#134397)" (llvm#135296)

This reapplies commit
llvm@232525f.

The original commit triggered a sanitizer failure when `Target` was
destroyed. In `Target::Destroy`, `DeleteCurrentProcess` was called, but
it did not destroy the thread creation breakpoints for the underlying
`ProcessGDBRemote` because `ProcessGDBRemote::Clear` was not called in
that path.

`Target `then proceeded to destroy its breakpoints, which resulted in a
call to the destructor of a `std::vector` containing the breakpoints.
Through a sequence of complicated events, destroying breakpoints caused
the reference count of the underlying `ProcessGDBRemote` to finally
reach zero. This, in turn, called `ProcessGDBRemote::Clear`, which
attempted to destroy the breakpoints. To do that, it would go back into
the Target's vector of breakpoints, which we are in the middle of
destroying.

We solve this by moving the breakpoint deletion into
`Process:DoDestroy`, which is a virtual Process method that will be
called much earlier.

(cherry picked from commit c2939b9)
adrian-prantl added a commit to swiftlang/llvm-project that referenced this pull request Apr 14, 2025
…tiondeletion_62

 Reland "[lldb] Clear thread-creation breakpoints in ProcessGDBRemote::Clear (llvm#134397)"
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…:Clear (llvm#134397)"

This reverts commit 232525f.

This change is causing test crashes while running
TestCompletion.py on Darwin systems, most of the CI runs
have failed since it has been merged in.
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…:Clear (llvm#134397)" (llvm#135296)

This reapplies commit
llvm@232525f.

The original commit triggered a sanitizer failure when `Target` was
destroyed. In `Target::Destroy`, `DeleteCurrentProcess` was called, but
it did not destroy the thread creation breakpoints for the underlying
`ProcessGDBRemote` because `ProcessGDBRemote::Clear` was not called in
that path.

`Target `then proceeded to destroy its breakpoints, which resulted in a
call to the destructor of a `std::vector` containing the breakpoints.
Through a sequence of complicated events, destroying breakpoints caused
the reference count of the underlying `ProcessGDBRemote` to finally
reach zero. This, in turn, called `ProcessGDBRemote::Clear`, which
attempted to destroy the breakpoints. To do that, it would go back into
the Target's vector of breakpoints, which we are in the middle of
destroying.

We solve this by moving the breakpoint deletion into
`Process:DoDestroy`, which is a virtual Process method that will be
called much earlier.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants